#!/usr/bin/env python
#
#       Customize.py
#
#       Copyright 2008 karthikeyan S.<kaarthikeyapreyan@gmail.com>
#
#       This program is free software; you can redistribute it and/or modify
#       it under the terms of the GNU General Public License as published by
#       the Free Software Foundation; either version 2 of the License, or
#       (at your option) any later version.
#
#       This program is distributed in the hope that it will be useful,
#       but WITHOUT ANY WARRANTY; without even the implied warranty of
#       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#       GNU General Public License for more details.
#
#       You should have received a copy of the GNU General Public License
#       along with this program; if not, write to the Free Software
#       Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
#       MA 02110-1301, USA.

import os
import wx

import help
import caselogic
import accessories
import resultdefinitions

from generatepyunit import PyFramework

class CustDefinitions:
    def __init__(self,baseframe):
        self.Inst=baseframe
        self.info=[]

    def gatherInfo(self,event):
        """
        Gather Info and genrate cases
        """
        self.custframe=wx.Frame(self.Inst,-1,"Custom Definitions",\
            size=(400,400))

        mysizer=wx.BoxSizer(wx.VERTICAL)

        infosizer=wx.BoxSizer(wx.VERTICAL)
        gensizer=wx.BoxSizer(wx.HORIZONTAL)

        modname=wx.StaticText(self.custframe, 1,"Module")
        self.modentry=wx.TextCtrl(self.custframe, 11,"",\
            style=wx.TE_LEFT|wx.EXPAND,size=(400,30))

        classname=wx.StaticText(self.custframe, 2,"Class")
        self.classentry=wx.TextCtrl(self.custframe, 21,"",\
            style=wx.TE_LEFT,size=(400,30))

        entityname=wx.StaticText(self.custframe, 3,"Function/Method")
        self.entityentry=wx.TextCtrl(self.custframe, 31,"",\
            style=wx.TE_LEFT,size=(400,30))

        argname=wx.StaticText(self.custframe, 4,"Arguments")
        self.argentry=wx.TextCtrl(self.custframe, 41,"",\
            style=wx.TE_LEFT,size=(400,30))

        infosizer.AddMany([modname,self.modentry,classname,self.classentry,\
            entityname,self.entityentry,argname,self.argentry])

        adan=wx.Button(self.custframe,5,"Add")
        gen=wx.Button(self.custframe,6,"Generate")
        quit=wx.Button(self.custframe,7,"Quit")
        fill=wx.StaticText(self.custframe,8,"\t\t")
        custhelp=wx.Button(self.custframe,9,"Help")

        gensizer.AddMany([adan,fill,custhelp,gen,quit])

        mysizer.Add(infosizer)
        mysizer.Add(gensizer)

        self.custframe.SetSizer(mysizer)
        mysizer.Fit(self.custframe)
        self.custframe.Show(True)

        if len(self.info):
            dlg = wx.MessageDialog(self.custframe, \
                'Do you want to clear the\nprevious customizations in buffer',\
                '', wx.OK|wx.CANCEL)
            if dlg.ShowModal() == wx.ID_OK:
                self.info=[]
            else :
                pass
            dlg.Destroy()

        self.custframe.Bind(wx.EVT_BUTTON,self.addAnother,id=5)
        self.custframe.Bind(wx.EVT_BUTTON,self.generate,id=6)
        self.custframe.Bind(wx.EVT_BUTTON,self.quit,id=7)
        self.custframe.Bind(wx.EVT_BUTTON,help.ModuleHelp\
            (self.custframe).customize,id=9)

    def addAnother(self,event):
        """
        Add another entity for generation
        """
        if self.modentry.GetValue() and \
            (self.classentry.GetValue() or self.entityentry.GetValue()):
            self.info.append([str(self.modentry.GetValue()),\
                str(self.classentry.GetValue()),str(self.entityentry.GetValue()),\
                str(self.argentry.GetValue())])
        self.modentry.SetValue("")
        self.classentry.SetValue("")
        self.entityentry.SetValue("")
        self.argentry.SetValue("")

    def quit(self,event):
        """
        Exit out of the application
        """
        self.custframe.Close()

    def generate(self,event):
        """
        Confirm and generate cases
        """
        temp=["Display Format [MODULE,CLASS.FUNCTION/METHOD,ARGUMENTS]\n"]
        temp.extend(self.info)
        temp=map(lambda id: str(id),temp)
        resultdefinitions.StatDisp(self.Inst,-1,\
            "PyTest Generated",['Customizations',"\n\t".join(temp)],flag=1)

        self.custframe.Close()
        if self.info:
            self.writecases(self.info)

    def writecases(self,entries):
        """
        Generate test cases
        """
        writefile= PyFramework()
        for mod in self.cachemodule(entries) :
            writefile.writefile("import %s\n"%mod)
        writefile.writeheader()
        writefile.writefile(" Custom module'''\n")

        for entry in entries:
            try :
                custmod=__import__(entry[0])
            except  ImportError, E:
                custmod=None

            if entry[3] :
                argvals=self.constructArginfo(entry)
            else :
                argvals=0

            if not custmod  :
                break
            elif not entry[2] :
                break
            elif entry[1] and entry[3] :
                self.argCases(writefile,argvals,entry[2],custmod,entry[1])
            elif entry[1] and not entry[3]:
                caselogic.ArgLogic().noArg(writefile,entry[2],mod=custmod,classmod=entry[1])
            elif (not entry[1] and entry[3]):
                self.argCases(writefile,argvals,entry[2],custmod)
            elif not entry[1] and not entry[3]:
                caselogic.ArgLogic().noArg(writefile,entry[2],mod=custmod,classmod=None)

        writefile.writefooter()
        writefile.closefile(fpath=os.getcwd(),fname='pytestgen_custom.py')
        
        if os.path.isfile('pytestgen_custom.py'):
            accessories.infobox(self.Inst,"Generated File Path: %s"\
                %os.path.abspath('pytestgen_custom.py'),\
                "TestCase Generated",wx.ICON_INFORMATION,size=wx.DEFAULT)  


    def constructArginfo(self,entry):
        """
        Create a system type Arginfo for the entity
        """
        argvals=[]
        args=entry[3]
        args=args.split(':')
        args=map(lambda x: eval(x),args)
        for arg in args :
            if arg[1] :
                argvals.append(arg[1])
            else :
                argvals.append(None)

        return argvals

    def cachemodule(self,entry):
        """
        Import Selected modules
        """
        modlist=[]
        for entries in entry:
            if entries[0] :
                modlist.append(entries[0])
        return modlist

    def argCases(self,fileobj,argvals,entity,mod,smclass=None):
        """
        Write cases for entities with arguments
        """
        temp=[]
        temp.extend(argvals)
        argnum=len(argvals)
        for index,arg in enumerate(argvals):
            if type(arg) == type(1) or type(arg) == type(True):
                argvals[index]='%s'%arg
            elif type(arg) == type("String"):
                argvals[index]="'%s'"%arg

        #Lower Boundary Arguments
        fileobj.writecases(mod.__name__,entity,0,'Fail',\
            comment="Without_Arg",classmod=smclass)
        # With only Arguments
        fileobj.writecases(mod.__name__,entity,argnum,'Pass',\
            arguments=argvals,comment="With_Only_Valid_Arguments",\
            classmod=smclass)


        #Invalid Argument
        fileobj.writecases(mod.__name__,entity,argnum,'Fail',\
            arguments=caselogic.ArgLogic().switch(temp,SNumArgs=1),\
            comment="With_OneInvalid_Arg",classmod=smclass)
        if len(argvals) >= 2:
            fileobj.writecases(mod.__name__,entity,argnum,'Fail',\
                arguments=caselogic.ArgLogic().switch(temp,SNumArgs=2),\
                comment="With_TwoInvalid_Args",classmod=smclass)

        #Upper Boundry Arguments
        argvals.append("'TestStr2'")
        fileobj.writecases(mod.__name__,entity,argnum+1,'Fail',\
            arguments=argvals,comment="With_Greater_Args_Than_Specified",\
            classmod=smclass)

        argvals.pop()
        argvals.pop()

        #With less Arguments  than specified
        fileobj.writecases(mod.__name__,entity,argnum-1,'Fail',\
            arguments=argvals,comment="With_Fewer_Args_Than_Specified",\
            classmod=smclass)

